﻿using System;
using System.Threading;
using OS.Common.Enums;

namespace OS.Common.Core
{
    /// <summary>
    /// 配置基类
    /// </summary>
    /// <typeparam name="TConfigType">配置信息</typeparam>
    /// <typeparam name="TConfigOwnerType">配置的使用者（防止在同一线程中同一配置类型有两个不同的使用者设置上下文配置信息）</typeparam>
    public class BaseConfigProvider<TConfigType, TConfigOwnerType> where TConfigType : class where TConfigOwnerType: class 
    {
        private static readonly AsyncLocal<TConfigType> ContextConfig = new AsyncLocal<TConfigType>();

        private TConfigType _config;

        /// <summary>
        /// 接口配置，优先级：上下文设置 => 实例设置 => 默认设置
        /// </summary>
        public TConfigType ApiConfig
        {
            get
            {
                if (ContextConfig.Value != null)
                    return ContextConfig.Value;

                if (_config == null && (_config = GetDefaultConfig()) == null)
                    throw new ArgumentNullException("当前配置信息为空，请通过构造函数中赋值，或者SetContextConfig方法设置当前上下文配置信息");

                return _config;
            }
        }

        /// <summary>
        /// 模块名称
        /// </summary>
        public string ModuleName { get; set; } = "default";

        /// <summary>
        /// 配置模式
        /// </summary>
        public ConfigProviderMode ConfigMode
        {
            get
            {
                if (ContextConfig.Value != null)
                    return ConfigProviderMode.Context;
                if (_config == null)
                    return ConfigProviderMode.Default;

                return ConfigProviderMode.Instance;
            }
        }

        /// <summary>
        /// 设置上下文配置信息，当前配置在当前上下文中有效
        /// </summary>
        /// <param name="config"></param>
        public static void SetContextConfig(TConfigType config)
        {
            ContextConfig.Value = config;
        }

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="config">配置信息</param>
        public BaseConfigProvider(TConfigType config)
        {
            if (config != null)
                _config = config;
        }

        /// <summary>
        /// 获取默认配置信息，如果上下文配置信息不存咋，且构造函数没有传入配置信息，执行此方法
        /// </summary>
        /// <returns></returns>
        protected virtual TConfigType GetDefaultConfig()
        {
            return null;
        }
    }
}